/*******************************************************************************
 * Copyright (c) 2011-11-24 @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> - initial API and implementation
 ******************************************************************************/
package org.redhat.auth.security.core;

import org.redhat.auth.security.data.DataModel;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
 * @since 2011-11-24
 */
public class AuthDaoAuthenticationProvider extends
		AbstractUserDetailsAuthenticationProvider {

	private DataModel ramsDataModel;

	public void setRamsDataModel(DataModel ramsDataModel) {
		this.ramsDataModel = ramsDataModel;
	}

	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		if (authentication.getCredentials() == null) {
			logger.debug("Authentication failed: no credentials provided");

			throw new BadCredentialsException(messages.getMessage(
					"AbstractUserDetailsAuthenticationProvider.badCredentials",
					"Bad credentials"), new NullPointerException(
					"Authentication failed: no credentials provided"));
		}

		String presentedPassword = authentication.getCredentials().toString();

		if (ramsDataModel == null) {
			throw new BadCredentialsException(
					"Authentication failed: a ramsDataModel must be set");
		}

		if (!ramsDataModel.validatePassword(userDetails.getUsername(),
				presentedPassword)) {
			throw new BadCredentialsException("Bad credentials");
		}
	}

	protected UserDetails retrieveUser(String username,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		UserDetails loadedUser;
		try {
			loadedUser = this.ramsDataModel.getUserByName(username);
		} catch (Exception repositoryProblem) {
			throw new AuthenticationServiceException(repositoryProblem
					.getMessage(), repositoryProblem);
		}

		if (loadedUser == null) {
			throw new AuthenticationServiceException(
					"UserDetailsService returned null, which is an interface contract violation");
		}
		return loadedUser;
	}

}
